﻿using System.Text.RegularExpressions;
/*
 * Created by SharpDevelop.
 * User: fred
 * Date: 9/09/2011
 * Time: 20:50
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

namespace ProviderAlloCine
{
	using System;
	using System.AddIn;
	using System.Collections.Generic;
	using System.IO;
	using System.Linq;
	using System.Xml.Linq;
	using System.Xml.Serialization;
	using System.Globalization;
	using MetaVideoEditorEvolved.AddIn.AddInViews;
	using MetaVideoEditorEvolved.AddIn.Entity;
	using MetaVideoEditorEvolved.Helper;
	
	[System.AddIn.AddIn("AlloCine",
	                    Version = "1.0.0.0",
	                    Description = "Fournisseur d'accès à AlloCine",
	                    Publisher = "Masy Freddy")]
	public class AlloCineManager : ProviderView
	{
		private XNamespace ns = "http://www.allocine.net/v6/ns/";
		private string apiInfoMovie = @"http://api.allocine.fr/rest/v3/movie?partner=YW5kcm9pZC12M3M&format=xml&profile=large&code=",
		apiTrailers = @"http://api.allocine.fr/rest/v3/media/AcVisionData_xml.asp?media=";
		private ConfigurationAddIn configurationAddIn;
		
		public AlloCineManager()
		{
			configurationAddIn = ConfigurationManager.Deserialize();
			
			if(configurationAddIn == null)
			{
				configurationAddIn = new ConfigurationAddIn()
				{
					TraceLevel = "Error"
				};
				
				ConfigurationManager.Serialize(configurationAddIn);
			}
			
			Tracer.TracerInstance.Level= string.IsNullOrEmpty(configurationAddIn.TraceLevel) ? TracerLevel.Error : (TracerLevel)Enum.Parse(typeof(TracerLevel), configurationAddIn.TraceLevel);
			Tracer.TracerInstance.FileName = "AlloCine";
		}
		
		public override System.Collections.Generic.List<ProviderSearchResult> FindPossible(ProviderSearchRequest request)
		{
			Tracer.TracerInstance.TraceInformation(string.Format("Start the AlloCine FindPossible (SearchName:{0}-Type{1})", request.Name, request.Type.ToString()));
			
			try
			{
				var api = new AlloCine.AlloCineApi();
				var response = api.Search(request.Name.Replace("é","e").Replace("è","e").Replace("ê","e").Replace("ç","c"), new []{AlloCine.TypeFilters.Movie, AlloCine.TypeFilters.TvSeries},50, 1);
				
				var results = new List<ProviderSearchResult>();
				
				if(response.MovieList!=null)
				{
					foreach (var movie in response.MovieList) {
						results.Add(new ProviderSearchResult()
						            {
						            	Id = !string.IsNullOrEmpty(movie.Code) ? int.Parse(movie.Code) : 0,
						            	OriginalName = movie.OriginalTitle,
						            	Name = !string.IsNullOrEmpty(movie.Title) ?  movie.Title : movie.OriginalTitle,
						            	Year = !string.IsNullOrEmpty(movie.ProductionYear) ? int.Parse(movie.ProductionYear) : 0,
						            	Picture = (movie.Poster != null && !string.IsNullOrEmpty(movie.Poster.Href)) ? new Uri(movie.Poster.Href) : null,
						            	Overview = (movie.CastingShort != null && !string.IsNullOrEmpty(movie.CastingShort.Actors)) ? movie.CastingShort.Actors : string.Empty,
						            	MediaUrl = (movie.LinkList != null && movie.LinkList.Any() && !string.IsNullOrEmpty(movie.LinkList[0].Href)) ? new Uri(movie.LinkList[0].Href) : null,
						            	Rating = (movie.Statistics != null && !string.IsNullOrEmpty(movie.Statistics.PressRating)) ? float.Parse(movie.Statistics.PressRating, CultureInfo.InvariantCulture) : 0.0F
						            });
					}
				}
				
				if(response.TvSeriesList!=null)
				{
					foreach (var serie in response.TvSeriesList) {
						results.Add(new ProviderSearchResult()
						            {
						            	Id = !string.IsNullOrEmpty(serie.Code) ? int.Parse(serie.Code) : 0,
						            	OriginalName = serie.OriginalTitle,
						            	Name = !string.IsNullOrEmpty(serie.Title) ?  serie.Title : serie.OriginalTitle,
						            	Year = !string.IsNullOrEmpty(serie.YearStart) ? int.Parse(serie.YearStart) : 0,
						            	Picture = (serie.Poster != null && !string.IsNullOrEmpty(serie.Poster.Href)) ? new Uri(serie.Poster.Href) : null,
						            	Overview = (serie.CastingShort != null && !string.IsNullOrEmpty(serie.CastingShort.Actors)) ? serie.CastingShort.Actors : string.Empty,
						            	MediaUrl = (serie.LinkList != null && serie.LinkList.Any() && !string.IsNullOrEmpty(serie.LinkList[0].Href)) ? new Uri(serie.LinkList[0].Href) : null,
						            	Rating = (serie.Statistics != null && !string.IsNullOrEmpty(serie.Statistics.PressRating)) ? float.Parse(serie.Statistics.PressRating, CultureInfo.InvariantCulture) : 0.0F
						            });
					}
				}
				
				Tracer.TracerInstance.TraceSuccessOperation(string.Format("End the AlloCine FindPossible (SearchName:{0}-Type{1}) with {2} items", request.Name, request.Type.ToString(), results.Count));
				
				return results;
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError("Exception in AlloCine FindPossible (SearchName:{0}-Type{1})", ex);
				throw new InvalidPluginException(Properties.Resources.UnknownError, ex);
			}
		}
		
		public override Movie FetchMovie(int movieId)
		{
			Tracer.TracerInstance.TraceInformation(string.Format("Start the AlloCine FechMovie (Id:{0})", movieId));
			Movie result = new Movie()
			{
				Countries = new List<string>(),
				Genres = new List<string>(),
				CastMembers = new List<CastMember>(),
				Backdrops = new List<Uri>(),
				Posters = new List<Uri>(),
				Trailers = new List<Trailer>(),
				Studios = new List<string>()
			};
			
			try
			{
				var api = new AlloCine.AlloCineApi();
				var response = api.MovieGetInfo(movieId,AlloCine.ResponseProfiles.Large, new []{AlloCine.TypeFilters.Movie},new string[0] , new [] {AlloCine.MediaFormat.Mpeg2});
				
				if (response.Error==null) {
					result.Id = movieId;
					result.OriginalTitle = response.OriginalTitle;
					result.Title = string.IsNullOrEmpty(response.Title) ? response.OriginalTitle : response.Title;
					result.Year = string.IsNullOrEmpty(response.ProductionYear) ? 0 : int.Parse(response.ProductionYear);
					
					if(response.NationalityList != null)
					{
						result.Countries = (from n in response.NationalityList
						                    select n.Value).ToList();
					}
					
					if(response.GenreList != null)
					{
						result.Genres = (from g in response.GenreList
						                 select g.Value).ToList();
					}
					
					result.Duration = string.IsNullOrEmpty(response.Runtime) ? 0 : int.Parse(response.Runtime) / 60;
					
					string overview = string.Empty;
					
					if(response.Synopsis != null)
					{
						result.Overview = response.Synopsis;
					}
					
					result.Rating = string.IsNullOrEmpty(response.Statistics.PressRating) ? 0.0F : float.Parse(response.Statistics.PressRating, CultureInfo.InvariantCulture) * 2.0F;
					
					if(response.CastMemberList != null)
					{
						result.CastMembers = (from c in response.CastMemberList
						                      select new CastMember
						                      {
						                      	FullName = c.Person.Name,
						                      	Activity = c.Activity == null ? string.Empty : c.Activity.Value,
						                      	Role = c.Role,
						                      	Picture = c.Picture == null ? null : new Uri(c.Picture.Href)
						                      }).ToList();
					}
					
					if(response.MediaList != null)
					{
						foreach (var mediaItem in response.MediaList) {
							switch (mediaItem.Type.Code) {
									//Poster
								case "31001":
								case "31125":
									if(mediaItem.Thumbnail != null &&
									   !string.IsNullOrEmpty(mediaItem.Thumbnail.Href))
									{
										result.Posters.Add(new Uri(mediaItem.Thumbnail.Href));
									}
									break;
									//Backdrop
								case "31006":
									if(mediaItem.Thumbnail != null &&
									   !string.IsNullOrEmpty(mediaItem.Thumbnail.Href))
									{
										result.Backdrops.Add(new Uri(mediaItem.Thumbnail.Href));
									}
									break;
									//Trailer
								case "31003":
								case "31016":
									var trailer = GetTrailer(mediaItem.Code.ToString());
									
									if(trailer != null)
									{
										result.Trailers.Add(trailer);
									}
									break;
							}
						}
					}
				}
				
				Tracer.TracerInstance.TraceSuccessOperation(string.Format("End the AlloCine FechMovie (Id:{0})", movieId));
				
				return result;
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError(string.Format("Exception in AlloCine FechMovie (Id:{0})", movieId), ex);
				throw new InvalidPluginException(Properties.Resources.UnknownError, ex);
			}
		}
		
		public override Season FetchSeason(string serieId, int seasonNumber)
		{
			Tracer.TracerInstance.TraceInformation(string.Format("Start the AlloCine FetchSeason (Id:{0})", serieId));
			Season result = new Season()
			{
				Images = new List<Uri>()
			};
			
			try
			{
				var api = new AlloCine.AlloCineApi();
				var serieResponse = api.TvSeriesGetInfo(int.Parse(serieId),AlloCine.ResponseProfiles.Large, new string[0] , new [] {AlloCine.MediaFormat.Mpeg2});
				int seasonCode = 0;
				foreach(AlloCine.Season s in serieResponse.SeasonList)
				{
					if(int.Parse(s.SeasonNumber) == seasonNumber)
					{
						seasonCode = int.Parse(s.Code);
					}
				}
				
				if(seasonCode != 0)
				{
					var response = api.TvSeriesSeasonGetInfo(seasonCode,AlloCine.ResponseProfiles.Large, new string[0] , new [] {AlloCine.MediaFormat.Mpeg2});
					if (response.Error==null) {
						result.Number = int.Parse(response.SeasonNumber);
						if(response.MediaList != null)
						{
							foreach (var mediaItem in response.MediaList) {
								switch (mediaItem.Type.Code) {
										//Poster
									case "31001":
									case "31125":
										if(mediaItem.Thumbnail != null &&
										   !string.IsNullOrEmpty(mediaItem.Thumbnail.Href))
										{
											result.Images.Add(new Uri(mediaItem.Thumbnail.Href));
										}
										break;
										//Backdrop
									case "31006":
										if(mediaItem.Thumbnail != null &&
										   !string.IsNullOrEmpty(mediaItem.Thumbnail.Href))
										{
											result.Images.Add(new Uri(mediaItem.Thumbnail.Href));
										}
										break;
										//Trailer
									case "31003":
									case "31016":
										// TODO: get trailer
										//var trailer = GetTrailer(mediaItem.Code.ToString(),
										//                       mediaItem.Version.lang.ToString());
										
										// if(trailer != null)
										// {
										//	result.Trailers.Add(trailer);
										// }
										break;
								}
							}
						}
					}
				}
				
				
				Tracer.TracerInstance.TraceSuccessOperation(string.Format("End the AlloCine FetchSeason (Id:{0})", serieId));
				
				return result;
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError(string.Format("Exception in AlloCine FetchSeason (Id:{0})", serieId), ex);
				throw new InvalidPluginException(Properties.Resources.UnknownError, ex);
			}
		}
		
		public override Serie FetchSerie(string serieId)
		{
			Tracer.TracerInstance.TraceInformation(string.Format("Start the AlloCine FechSerie (Id:{0})", serieId));
			Serie result = new Serie()
			{
				Genres = new List<string>(),
				Studios = new List<string>(),
				Posters = new List<Uri>(),
				Backdrops = new List<Uri>(),
				CastMembers = new List<CastMember>(),
				Graphicals = new List<Uri>()
			};
			
			try
			{
				var api = new AlloCine.AlloCineApi();
				var response = api.TvSeriesGetInfo(int.Parse(serieId),AlloCine.ResponseProfiles.Large, new string[0] , new [] {AlloCine.MediaFormat.Mpeg2});
				
				if (response.Error==null) {
					result.Id = serieId;
					result.Name = string.IsNullOrEmpty(response.Title) ? response.OriginalTitle : response.Title;
					result.Year = string.IsNullOrEmpty(response.YearStart) ? 0 : int.Parse(response.YearStart);
					
					string overview = string.Empty;
					
					if(response.Synopsis != null)
					{
						result.Overview = response.Synopsis;
					}
					
					if(response.GenreList != null)
					{
						result.Genres = (from g in response.GenreList
						                 select g.Value).ToList();
					}
					
					result.Duration = 0;
					
					result.Rating = string.IsNullOrEmpty(response.Statistics.PressRating) ? 0.0F : float.Parse(response.Statistics.PressRating, CultureInfo.InvariantCulture) * 2.0F;
					
					if(response.CastMemberList != null)
					{
						result.CastMembers = (from c in response.CastMemberList
						                      select new CastMember
						                      {
						                      	FullName = c.Person.Name,
						                      	Activity = c.Activity == null ? string.Empty : c.Activity.Value,
						                      	Role = c.Role,
						                      	Picture = c.Picture == null ? null : new Uri(c.Picture.Href)
						                      }).ToList();
					}
					
					if(response.MediaList != null)
					{
						foreach (var mediaItem in response.MediaList) {
							switch (mediaItem.Type.Code) {
									//Poster
								case "31001":
								case "31125":
									if(mediaItem.Thumbnail != null &&
									   !string.IsNullOrEmpty(mediaItem.Thumbnail.Href))
									{
										result.Posters.Add(new Uri(mediaItem.Thumbnail.Href));
									}
									break;
									//Backdrop
								case "31006":
									if(mediaItem.Thumbnail != null &&
									   !string.IsNullOrEmpty(mediaItem.Thumbnail.Href))
									{
										result.Backdrops.Add(new Uri(mediaItem.Thumbnail.Href));
									}
									break;
									//Trailer
//								case "31003":
//								case "31016":
//									var trailer = GetTrailer(mediaItem.Code.ToString(),
//									                       mediaItem.Version.lang.ToString());
//									
//									if(trailer != null)
//									{
//										result.Trailers.Add(trailer);
//									}
//									break;
							}
						}
					}
				}
				
				Tracer.TracerInstance.TraceSuccessOperation(string.Format("End the AlloCine FechTvSerie (Id:{0})", serieId));
				
				return result;
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError(string.Format("Exception in AlloCine FechTvSerie (Id:{0})", serieId), ex);
				throw new InvalidPluginException(Properties.Resources.UnknownError, ex);
			}
		}
		
		public override Episode FetchEpisode(string serieId, int seasonNumber, int episodeNumber)
		{
			Tracer.TracerInstance.TraceInformation(string.Format("Start the AlloCine FetchEpisode (Id:{0})", serieId));
			Episode result = new Episode()
			{
				Images = new List<Uri>(),
				GuestStars = new List<string>(),
				Writers = new List<string>(),
				Directors = new List<string>()
			};
			
			try
			{
				var api = new AlloCine.AlloCineApi();
				var serieResponse = api.TvSeriesGetInfo(int.Parse(serieId),AlloCine.ResponseProfiles.Large, new string[0] , new [] {AlloCine.MediaFormat.Mpeg2});
				int seasonCode = 0;
				foreach(AlloCine.Season s in serieResponse.SeasonList)
				{
					if(int.Parse(s.SeasonNumber) == seasonNumber)
					{
						seasonCode = int.Parse(s.Code);
					}
				}
				
				if(seasonCode != 0)
				{
					var seasonResponse = api.TvSeriesSeasonGetInfo(seasonCode,AlloCine.ResponseProfiles.Large, new string[0] , new [] {AlloCine.MediaFormat.Mpeg2});
					int episodeCode = 0;
					foreach (AlloCine.Episode e in seasonResponse.EpisodeList) {
						if(int.Parse(e.EpisodeNumberSeason) == episodeNumber)
						{
							episodeCode = int.Parse(e.Code);
						}
					}
					
					if(episodeCode != 0)
					{
						var response = api.TvSeriesEpisodeGetInfo(episodeCode,AlloCine.ResponseProfiles.Large, new string[0] , new [] {AlloCine.MediaFormat.Mpeg2});
						
						if (response.Error==null) {
							result.Id = episodeCode;
							result.Name = string.IsNullOrEmpty(response.Title) ? response.OriginalTitle : response.Title;
							result.Year = 0;
							result.Number = episodeNumber;
							result.SeasonNumber = seasonNumber;
							
							string overview = string.Empty;
							
							if(response.Synopsis != null)
							{
								result.Overview = response.Synopsis;
							}
							
							result.Rating = string.IsNullOrEmpty(response.Statistics.PressRating) ? 0.0F : float.Parse(response.Statistics.PressRating, CultureInfo.InvariantCulture) * 2.0F;
							
//							if(response.MediaList != null)
//							{
//								foreach (var mediaItem in response.MediaList) {
//									switch (mediaItem.Type.Code) {
//											//Poster
//										case "31001":
//										case "31125":
//											if(mediaItem.Thumbnail != null &&
//											   !string.IsNullOrEmpty(mediaItem.Thumbnail.Href))
//											{
//												result.Posters.Add(new Uri(mediaItem.Thumbnail.Href));
//											}
//											break;
//											//Backdrop
//										case "31006":
//											if(mediaItem.Thumbnail != null &&
//											   !string.IsNullOrEmpty(mediaItem.Thumbnail.Href))
//											{
//												result.Backdrops.Add(new Uri(mediaItem.Thumbnail.Href));
//											}
//											break;
//											//Trailer
//										case "31003":
//										case "31016":
//											// TODO: get trailer
//											//var trailer = GetTrailer(mediaItem.Code.ToString(),
//											//                       mediaItem.Version.lang.ToString());
//											
//											// if(trailer != null)
//											// {
//											//	result.Trailers.Add(trailer);
//											// }
//											break;
//									}
//								}
//							}
						}
					}
				}
				
					
				Tracer.TracerInstance.TraceSuccessOperation(string.Format("End the AlloCine FetchEpisode (Id:{0})", serieId));
				
				return result;
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError(string.Format("Exception in AlloCine FetchEpisode (Id:{0})", serieId), ex);
				throw new InvalidPluginException(Properties.Resources.UnknownError, ex);
			}
		}
		
		private Trailer GetTrailer(string code)//,string langage)
		{
			try
			{
				AlloCine.AlloCineApi api = new AlloCine.AlloCineApi();
				var response = api.MediaGetInfo(int.Parse(code),AlloCine.ResponseProfiles.Large, new [] {AlloCine.MediaFormat.Mpeg2});
				
				if(response.Error == null)
				{
					Trailer trailer =new Trailer();
					
					var trailerQuality = response.Thumbnail.Href;
					trailer.HighQuality = trailer.MediumQuality = trailer.LowQuality = trailer.DefaultPath = string.IsNullOrEmpty(trailerQuality) ? null : new Uri(trailerQuality);
					
//					switch (language) {
//						case "6001":
//							trailer.Language = Language.French;
//							break;
//						case "6002":
//							trailer.Language = Language.English;
//							break;
//						default:
//							trailer.Language = Language.Unknown;
//							break;
//					}
					
					return trailer;
				}
				else
				{
					throw new Exception(response.Error.Value);
				}
//				var resultWebRequest = DownloadManager.RetrieveXmlWebRequest(apiTrailers + code);
//				
//				if(resultWebRequest != null)
//				{
//					AcVision searchTrailer = new XmlSerializer(typeof(AcVision)).Deserialize(resultWebRequest.Root.CreateReader()) as AcVision;
//					
//					if(searchTrailer != null &&
//					   searchTrailer.AcVisionVideo != null)
//					{
//						Trailer trailer = new Trailer();
//						
//						var trailerQuality = searchTrailer.AcVisionVideo.hd_path;
//						trailer.HighQuality = trailer.DefaultPath = string.IsNullOrEmpty(trailerQuality) ? null : new Uri(trailerQuality);
//
//						trailerQuality = searchTrailer.AcVisionVideo.md_path;
//						trailer.MediumQuality = string.IsNullOrEmpty(trailerQuality) ? null : new Uri(trailerQuality);
//						trailer.DefaultPath = trailer.DefaultPath != null ? trailer.DefaultPath : new Uri(trailerQuality);
//
//						trailerQuality = searchTrailer.AcVisionVideo.ld_path;
//						trailer.LowQuality = string.IsNullOrEmpty(trailerQuality) ? null : new Uri(trailerQuality);
//						trailer.DefaultPath = trailer.DefaultPath != null ? trailer.DefaultPath : new Uri(trailerQuality);
//
//						switch (language) {
//							case "6001":
//								trailer.Language = Language.French;
//								break;
//							case "6002":
//								trailer.Language = Language.English;
//								break;
//							default:
//								trailer.Language = Language.Unknown;
//								break;
//						}
//						
//						return trailer;
//					}
//				}
			}
			catch(Exception ex)
			{
				//Tracer.TracerInstance.TraceError(string.Format("Exception in AlloCine GetTrailer (code={0},language={1}", code, language), ex);
				Tracer.TracerInstance.TraceError(string.Format("Exception in AlloCine GetTrailer (code={0}", code), ex);
				return null;
			}
		}
		
		public override void ShowOption()
		{
			new Option(configurationAddIn).ShowDialog();
		}
		
		public override bool HasOption()
		{
			return true;
		}
	}
}
